my distraction free colorscheme search ended with vim-colors-duochrome and had become the only vim colorscheme i use for coding and writing. This duochromatic light colorscheme begged for a properly tweaked dark colorscheme counterpart and diff configuration replacement for the vim-quantum and vim-one colorschemes used for such.
Tweaking the colorscheme was rote enough given enough iterations to find colours i could live with. The real effort consumed during this process was maintaining the theme.vim plugin with the various hex colour palette changes for dynamic colour column, window borders, statusline, indent highlighting, cursorline and other dynamic context decorations—the traditional way for augmenting a colorscheme, with external context related highlight commands.
or rather, code optimization. Moving the context rules from the theme and user interface control .vimrc plugins to the colorscheme plugin itself (rendering it an non-standard colorscheme file) reduced the vim configuration significantly by removing colour values, highlight commands and the associated display control logic with..
if !exists('g:duochrome_cursorline') | let g:duochrome_cursorline = 0 | endif
if !exists('g:duochrome_insert') | let g:duochrome_insert = 0 | endif
if !exists('g:duochrome_markdown') | let g:duochrome_markdown = 0 | endif
if !exists('g:duochrome_relative') | let g:duochrome_relative = 0 | endif
if !exists('g:duochrome_ruler') | let g:duochrome_ruler = 0 | endif
if !exists('g:duochrome_split') | let g:duochrome_split = 0 | endif
if !has('gui_running') | let g:duochrome_cursorline = 1 | endif
where,
global variable | 0 | 1 | 2 |
---|---|---|---|
duochrome_cursorline | dfm | highlight | underline |
duochrome_insert | normal mode | insert mode | |
duochrome_markdown | code | markdown | |
duochrome_relative | line number | relative number | |
duochrome_ruler | column off | cursor column | fixed column |
duochrome_split | single window | split windows |
Context toggles of the global variables in the .vimrc file (actually, the vim-duochrome plugin) can now be magically interpreted by the colorscheme..
highlighting is differentiated for code, markdown and diff, whether in normal or insert mode..
if empty($DISPLAY)
call s:h('CursorLine', { 'cterm': 'underline' })
elseif g:duochrome_insert && g:duochrome_markdown
if g:duochrome_cursorline == 2
call s:h('CursorLine', { 'fg': s:high_contrast, 'gui': 'underline' })
else
call s:h('CursorLine', { 'fg': s:high_contrast, 'bg': g:duochrome_cursorline ? s:cursor_line : s:bg })
endif
elseif g:duochrome_cursorline == 2
call s:h('CursorLine', { 'gui': 'underline' })
else
call s:h('CursorLine', { 'bg': g:duochrome_cursorline ? s:cursor_line : s:bg })
endif
Note: s:h() is a function (borrowed from vim-hemisu) that sets the vim highlight command. Refer to the plugin source.
to show current line number only or relative line numbers only..
if g:duochrome_relative
call s:h('CursorLineNr', { 'fg': s:bg })
call s:h('LineNr', { 'fg': s:blue })
else
call s:h('CursorLineNr', { 'fg': g:duochrome_insert ? s:bg : s:blue })
call s:h('LineNr', { 'fg': s:bg })
endif
if &diff
call s:h('DiffAdd', { 'bg': s:statusline, 'fg': s:green })
call s:h('DiffDelete', { 'bg': s:statusline, 'fg': s:red })
call s:h('DiffChange', { 'bg': s:statusline, 'fg': s:yellow })
call s:h('DiffText', { 'bg': s:statusline, 'fg': s:constant })
else
call s:h('DiffAdd', { 'fg': s:green })
call s:h('DiffDelete', { 'fg': s:red })
call s:h('DiffChange', { 'fg': s:yellow })
call s:h('DiffText', { 'fg': s:constant })
endif
highlight becomes a visual window separator as well when there are split windows..
call s:h('StatusLine', { 'bg': s:statusline, 'fg': s:norm_subtle })
call s:h('User1', { 'bg': g:duochrome_split ? s:statusline : s:bg, 'fg': s:norm_subtle })
call s:h('User2', { 'bg': g:duochrome_split ? s:statusline : s:bg, 'fg': s:norm_very_subtle })
call s:h('User3', { 'bg': g:duochrome_split ? s:statusline : s:bg, 'fg': s:red })
call s:h('StatusLineNC', { 'bg': g:duochrome_split ? s:statusline : s:bg })
call s:h('ColorColumn', { 'bg': g:duochrome_ruler == 1 ? s:column : s:guide })
the remainder of the vim-duochrome plugin contains the theme and user interface rules (autocmds) for dynamically setting the colorscheme and statusline based on the context or manual keymap toggle applied as per my personal distraction free workflow..
The beauty of this approach is, while coupling the colorscheme to the plugin logic (a defiance of colorscheme norms), the preservation of session state information permits toggling between light and dark background themes with a single vim command (versus the former approach requiring external highlight initialization and keeping track of what context highlight is at play).
Toggling a display attribute simply requires a background refresh and any other display attributes are handled accordingly simplifying the plugin logic enormously. Hence, the binding of the theme.vim, ui.vim and duochrome.vim plugins into a single plugin creating a dynamic colorscheme (as opposed to the traditional static colorscheme).
At the same time, runtime initialization of the global variables to sane defaults, still allows this colorscheme to be used simply as a traditional static vim colorscheme. In this case, a user need only copy the colorscheme file to their vim colors folder (versus loading the complete plugin and its dependencies).